package grammar

import (
	"fmt"
	"unsafe"
)

type A [0][256]int

type S struct {
	x A
	y [1 << 30]A
	z [1 << 30]struct{}
}

type T [1 << 30]S

// Calc 不含非零尺寸字段的结构体类型的尺寸为零。一个长度为零或元素尺寸为零的数组类型的
// 尺寸也是零。这些可以通过下面这个程序来验证。该程序打印出三个 0。
func Calc() {
	var a A
	var s S
	var t T
	println(unsafe.Sizeof(a))
	println(unsafe.Sizeof(s))
	println(unsafe.Sizeof(t))
}

// 位移按照箭头方向
func BitCalc() {
	i := 1 << 30
	fmt.Println(i)

	ii := 1 >> 30
	fmt.Println(ii)
}

func MemCalc() {
	var x [1 << 62]struct{}

	fmt.Println(x)

}

var g *[0]int
var a, b [0]int

func f() *[0]int {
	return new([0]int)
}

func CalcEqual() {
	// x 和 y 被分配在栈上。
	var x, y, z, w [0]int
	// 使 z 和 w 逃逸到堆上。
	g = &z
	g = &w
	println(&b == &a)  // false
	println(&x == &y)  // false
	println(&z == &w)  // true
	println(&z == f()) // true

}

const N = 8

var n = 8

func RangeN() {
	for i := range [N]struct{}{} {
		print(i)
	}
	println()
	for i := range [N][0]int{} {
		print(i)
	}
	println()
	for i := range make([][0]int, n) {
		print(i)
	}
	println()
}

func RangeCopy() {
	var a = [...]int{1, 2, 3}
	//普通遍历相当于a的副本在遍历, 需要加上&a
	for i, n := range &a {
		if i == 0 {
			a[1], a[2] = 8, 9
		}
		print(n)
	}
}

func RangePoint() {
	var s = []int{1, 2, 3}
	for i, n := range s {
		if i == 0 {
			s[1], s[2] = 8, 9
		}
		print(n)
	}
}

func ArrayPoint() {
	var a = [128]int{3: 789}
	var pa = &a
	// 无需复制数来遍历数组元素。
	// 复制一个指针的成本很低。
	for i, v := range pa {
		_, _ = i, v
	}
	// 通过数组指针获取数组的长度和容量。
	_, _ = len(pa), cap(pa)
	// 通过数组指针访问数组元素。
	_ = pa[3]
	pa[3] = 555
	// 从数组指针派生切片。
	var _ = pa[:]
}
